﻿#ifndef _SOCK_H_
#define _SOCK_H_

#include "net_err.h"
#include "exmsg.h"
#include "ipaddr.h"
#include "nlist.h"

#define SOCK_WAIT_READ (1 << 0)
#define SOCK_WAIT_WRITE (1 << 1)
#define SOCK_WAIT_CONN (1 << 2)
#define SOCK_WAIT_ALL (1 << 3)

struct x_sockaddr_in;

typedef int x_socklen_t;

// socket创建时所需要的参数
typedef struct _sock_crate_t
{
    int family;
    int type;
    int protocol;
} sock_create_t;

// socket发送相关的参数
typedef struct _sock_data_t
{
    uint8_t *buf;
    size_t len;
    ssize_t comply; // 记录发送的数据长度
    int flags;
    struct x_sockaddr_in *addr;
    x_socklen_t *addr_len;
} sock_data_t;

typedef struct _sock_wait_t
{
    sys_sem_t sem; // 等待同步信号量
    net_err_t err;
    int waiting; // 等待线程数
} sock_wait_t;

// setopt相关参数
typedef struct _sock_opt_t
{
    int level;
    int optname;
    const char *optval;
    int len;
} sock_opt_t;

// connect请求相关参数
typedef struct _sock_conn_t
{
    const struct x_sockaddr *addr;
    x_socklen_t addrlen;
} sock_conn_t;

// bind请求相关参数
typedef struct _sock_bind_t
{
    const struct x_sockaddr *addr;
    x_socklen_t addrlen;
} sock_bind_t;

typedef struct _sock_req_t
{
    int sockfd;

    union
    {
        sock_create_t create;
        sock_data_t data;
        sock_opt_t opt;
        sock_conn_t connect;
        sock_bind_t bind;
    };

    sock_wait_t *wait;
    int wait_tmo; // 等待超时时间
} sock_req_t;

struct _sock_t;

// socket回调函数表
typedef struct _sock_ops_t
{
    net_err_t (*close)(struct _sock_t *sock);
    net_err_t (*sendto)(struct _sock_t *s, const void *buf, size_t len, int flags,
                        const struct x_sockaddr *dest, x_socklen_t dest_len, ssize_t *result_len);
    net_err_t (*send)(struct _sock_t *s, const void *buf, size_t len, int flags, ssize_t *result_len);
    net_err_t (*recvfrom)(struct _sock_t *s, void *buf, size_t len, int falgs,
                          struct x_sockaddr *dest, x_socklen_t *dest_len, ssize_t *result_len);
    net_err_t (*recv)(struct _sock_t *s, void *buf, size_t len, int flags, ssize_t *result_len);
    net_err_t (*setopt)(struct _sock_t *s, int level, int optname, const char *optval, int optlen);
    net_err_t (*connect)(struct _sock_t *s, const struct x_sockaddr *addr, x_socklen_t addrlen);
    net_err_t (*bind)(struct _sock_t *s, const struct x_sockaddr *addr, x_socklen_t addrlen);
    void (*destroy)(struct _sock_t *s);
} sock_ops_t;

typedef struct _sock_t
{
    uint16_t local_port;
    ipaddr_t local_ipaddr;
    uint16_t remote_port;
    ipaddr_t remote_ipaddr;

    const sock_ops_t *ops;
    int family;   // ip协议类型
    int protocol; // 传输协议类型
    int recv_tmo; // 接受超时时间
    int send_tmo; // 发送超时时间
    int err;      // 错误码
    nlist_node_t node;

    sock_wait_t *recv_wait;
    sock_wait_t *send_wait;
    sock_wait_t *conn_wait;
} sock_t;

net_err_t socket_init();
net_err_t sock_init(sock_t *sock, int family, int protocol, const sock_ops_t *ops);
net_err_t sock_create_req_in(struct _func_msg_t *msg);
net_err_t sock_sendto_req_in(struct _func_msg_t *msg);
net_err_t sock_send_req_in(struct _func_msg_t *msg);
net_err_t sock_recvfrom_req_in(struct _func_msg_t *msg);
net_err_t sock_recv_req_in(struct _func_msg_t *msg);
net_err_t sock_setsockopt_req_in(struct _func_msg_t *msg);
net_err_t sock_connect_req_in(struct _func_msg_t *msg);
net_err_t sock_bind_req_in(struct _func_msg_t *msg);
net_err_t sock_close_req_in(struct _func_msg_t *msg);
net_err_t sock_uninit(sock_t *sock);

net_err_t sock_wait_init(sock_wait_t *wait);
void sock_wait_destroy(sock_wait_t *wait);
void sock_wait_add(sock_wait_t *wait, int tmo, sock_req_t *req);
net_err_t sock_wait_enter(sock_wait_t *wait, int tmo);
void sock_wait_leave(sock_wait_t *wait, net_err_t err);
void sock_wakeup(sock_t *sock, int type, int err);

// 通用调用接口
net_err_t sock_setopt(struct _sock_t *s, int level, int optname, const char *optval, int optlen);
net_err_t sock_connect(struct _sock_t *s, const struct x_sockaddr *addr, x_socklen_t addrlen);
net_err_t sock_send(struct _sock_t *s, const void *buf, size_t len, int flags, ssize_t *result_len);
net_err_t sock_recv(struct _sock_t *s, void *buf, size_t len, int flags, ssize_t *result_len);
net_err_t sock_bind(struct _sock_t *s, const ipaddr_t *ip, int port);

#endif